﻿Imports System.Windows.Forms
Imports System.Drawing
Imports System.Runtime.InteropServices

Public Class ControlFormater

    Private Shared _instance As ControlFormater

    Public Shared Function GetInstance() As ControlFormater
        If _instance Is Nothing Then _
            _instance = New ControlFormater
        Return _instance
    End Function


    Private _referenceForm As New ReferenceForm

    Private borderColor As Color = Color.Black   ' default border color is black
    Private Shared WM_NCPAINT As Integer = &H85   ' WM_NCPAINT message
    Private Shared WM_ERASEBKGND As Integer = &H14   ' WM_ERASEBKGND message
    Private Shared WM_PAINT As Integer = &HF   ' WM_PAINT message

    'The GetDCEx function retrieves a handle to a display device context
    '(DC) for the client area of a specified window
    <DllImport("user32.dll")> _
    Private Shared Function GetDCEx(ByVal hwnd As IntPtr, ByVal hrgnclip As IntPtr, ByVal fdwOptions As UInteger) As IntPtr
    End Function
    'the ReleaseDC function releases a device context (DC)
    <DllImport("user32.dll")> _
    Private Shared Function ReleaseDC(ByVal hwnd As IntPtr, ByVal hDC As IntPtr) As Integer
    End Function

    Private Sub New()
    End Sub

    Public Sub RegisterControl(ByVal c As Control)

        Call RegisterEvents(c)
        Call SetBorder(c)

    End Sub

    Public Sub RegisterControls(ByRef cc As Control.ControlCollection, Optional ByVal recursive As Boolean = True)
        For Each c As Control In cc
            Call RegisterControl(c)
            If recursive AndAlso c.Controls.Count > 0 Then
                Call RegisterControls(c.Controls)
            End If
        Next
    End Sub

    Private Sub RegisterEvents(ByRef c As Control)
        AddHandler c.Enter, AddressOf Me.ControlEnterEventHandler
        AddHandler c.Leave, AddressOf Me.ControlLeaveEventHanlder
        ' AddHandler c.Paint, AddressOf Me.PaintControl
    End Sub

    Private Sub ControlEnterEventHandler(ByVal sender As Object, ByVal e As EventArgs)
        If TypeOf sender Is TextBox OrElse _
            TypeOf sender Is ComboBox Then
            sender.BackColor = System.Drawing.Color.Khaki
        End If
        'If TypeOf sender Is TextBox Then
        '    DirectCast(sender, TextBox).BorderStyle = BorderStyle.None
        'End If
    End Sub

    Private Sub ControlLeaveEventHanlder(ByVal sender As Object, ByVal e As EventArgs)
        If TypeOf sender Is TextBox OrElse _
            TypeOf sender Is ComboBox Then
            sender.ResetBackColor()
        End If
        'If TypeOf sender Is TextBox Then
        '    DirectCast(sender, TextBox).BorderStyle = _referenceForm.TextBox1.BorderStyle
        'End If
    End Sub

    Private Sub SetBorder(ByRef c As Control)
        If TypeOf c Is TextBox Then
            CType(c, TextBox).BorderStyle = _referenceForm.TextBox1.BorderStyle
        End If

        If TypeOf c Is ComboBox Then
            CType(c, ComboBox).FlatStyle = _referenceForm.ComboBox1.FlatStyle
        End If

        If TypeOf c Is Button Then
            CType(c, Button).FlatStyle = _referenceForm.Button1.FlatStyle
        End If
    End Sub

    Private Sub PaintControl(ByVal sender As Object, ByVal e As PaintEventArgs)
        If TypeOf sender Is TextBox Then
            e.Graphics.DrawRectangle(Pens.Red, sender.X, sender.Y, sender.Width - 1, sender.Height - 1)
        End If
    End Sub

    ' message - a message from control's WndProc(ref Message m) method
    ' width - controls' width
    ' height - controls' height
    Public Sub DrawBorder(ByRef message As Message, ByVal width As Integer, ByVal height As Integer)
        If message.Msg = WM_NCPAINT OrElse message.Msg = WM_ERASEBKGND OrElse message.Msg = WM_PAINT Then
            'get handle to a display device context
            Dim hdc As IntPtr = GetDCEx(message.HWnd, New IntPtr(1), 1 Or &H20)

            If hdc <> IntPtr.Zero Then
                'get Graphics object from the display device context
                Dim graphics__1 As Graphics = Graphics.FromHdc(hdc)
                Dim rectangle As New Rectangle(0, 0, width, height)
                ControlPaint.DrawBorder(graphics__1, rectangle, borderColor, ButtonBorderStyle.Solid)

                message.Result = New IntPtr(1)
                ReleaseDC(message.HWnd, hdc)
            End If
        End If
    End Sub

    Public Shared Sub FormatCurrencyEventHandler(ByVal sender As Object, ByVal e As ConvertEventArgs)
        ' Fixed: Das zurück parsen funktioniert nicht. e.Value = CDbl(e.Value).ToString("C", (New System.Globalization.CultureInfo("de-DE")).NumberFormat)
        e.Value = CDbl(e.Value).ToString("###,###,##0.00")
        If IsNumeric(e.Value) Then
            If CDbl(e.Value) >= 0 Then
                CType(sender, Binding).Control.ForeColor = Color.Green
            Else
                CType(sender, Binding).Control.ForeColor = Color.Red
            End If
        End If
    End Sub

End Class
